/*
 *所有关于Ads_Task类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*Ads_TaskService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using DGZImp.Core.BaseProvider;
using DGZImp.Core.Extensions.AutofacManager;
using DGZImp.AdsProject.DomainModels;
using System.Linq;
using DGZImp.Core.Utilities;
using System.Linq.Expressions;
using DGZImp.Core.Extensions;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using DGZImp.AdsProject.IRepositories;
using System.Net;
using DGZImp.Core.EFDbContext;
using SqlSugar;
using DGZImp.Core.DbSqlSugar;
using DGZImp.Core.Exceptions;
using System;
using DGZImp.AdsProject.Enums;
using DGZImp.Core.ManageUser;
using AutoMapper;
using System.Diagnostics;
using DGZImp.AdsProject.Dtos;
using Newtonsoft.Json;
using DGZImp.Core.UserManager;
using System.Security.Claims;
using System.Threading.Tasks;

namespace DGZImp.AdsProject.Services
{
    public partial class Ads_TaskService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IAds_TaskRepository _repository;//访问数据库
        public ISqlSugarClient SysDb = AutofacContainerModule.GetService<SysDbContext>()?.SqlSugarClient;
        WebResponseContent webResponse = new WebResponseContent();
        private readonly IMapper _mapper;
        private readonly Ads_TaskLogService _taskLog;

        [ActivatorUtilitiesConstructor]
        public Ads_TaskService(
            IAds_TaskRepository dbRepository,
            IHttpContextAccessor httpContextAccessor,
            IMapper mapper,
            Ads_TaskLogService taskLog
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            _repository = dbRepository;
            _mapper = mapper;
            _taskLog = taskLog;
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
        }

        public override WebResponseContent Del(object[] keys, bool delList = true)
        {
            // 如果主键是 long 类型，用 GetLong 转换
            var ids = keys.Select(s => s.GetLong()).ToList();
            var delIds = new List<long>();

            // 检查任务状态，只有状态为 0（发起状态）的任务可以删除
            foreach (var id in ids)
            {
                var item = repository.DbContext.Queryable<Ads_Task>()
                                    .Where(t => t.TaskId == id)
                                    .FirstOrDefault();
                if (item != null && item.Status != 0)
                {
                    return webResponse.Error($"当前任务状态不是发起状态({item.TaskCode})，不可删除");
                }
                delIds.Add(id); // 添加到待删除列表
            }

            // 逻辑删除：将 IsValid 设置为 0
            repository.DbContext.Updateable<Ads_Task>()
                      .SetColumns(t => t.IsValid == 0) // 逻辑删除标记
                      .Where(t => t.IsValid == 1 && delIds.Contains(t.TaskId)) // 只更新有效的数据
                      .ExecuteCommand();

            // 返回成功响应
            return webResponse.OK("删除成功");
        }

        /// <summary>
        /// 新增或处理异常任务
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<long> AddOrUpdate(AbnormalTaskDto dto)
        {
            long id = 0;
            //检查入参
            if (dto.TaskId>0 && !dto.Status.HasValue)
            {
                throw new AppException($"更新时状态不可为空，请核对！");
            }

            bool inTrans = _repository.SqlSugarClient.Ado.Transaction != null;
            if (!inTrans) _repository.SqlSugarClient.Ado.BeginTran();
            try
            {
                if (dto.TaskId == 0)//新增任务
                {
                    var code = GenerateCode();
                    if (string.IsNullOrEmpty(code))
                    {
                        throw new AppException($"生成编号为空，请核对！");
                    }
                    Ads_Task data = _mapper.Map<Ads_Task>(dto);
                    data.TaskCode = code;
                    data.Initiator = UserContext.Current.UserName;
                    data.Status = (int)AbnormalTaskEnum.TOCLAIM;
                    data.Priority = dto.Priority;
                    //新增异常类型
                    await _repository.DbContext.DoInsertAsync(data);
                    id = data.TaskId;
                    //添加任务日志
                    await _taskLog.InsertLog(id, AbnormalLogActionEnum.START);
                }
                else//处理任务
                {
                    id = dto.TaskId;
                    var task = await _repository.DbContext.Queryable<Ads_Task>().Where(a => a.TaskId == dto.TaskId).FirstAsync();
                    
                    #region 区分修改还是业务操作
                    if (dto.isUpdate)
                    {
                        //修改只能改新增部分内容
                        await _repository.DbContext.Updateable<Ads_Task>()
                            .SetColumns(a => a.EquipmentCodes == dto.EquipmentCodes)
                            .SetColumns(a => a.Priority == dto.Priority)
                            .SetColumns(a => a.InitiatorRemarks == dto.InitiatorRemarks)
                            .SetColumns(a => a.InitiatorAttachments == dto.InitiatorAttachments)
                            .SetColumns(a => a.AbnormalTypeId == dto.AbnormalTypeId)
                            .SetColumns(a => a.ModifyTime == DateTime.Now)
                            .Where(a => a.TaskId == dto.TaskId)
                            .ExecuteCommandAsync();
                    }
                    else
                    {
                        //业务操作只能改非新增内容
                        AbnormalTaskEnum taskStatus = AbnormalTaskEnum.TOCLAIM;//任务原本状态
                        AbnormalTaskEnum dtoStatus = AbnormalTaskEnum.TOCLAIM;//dto带的状态
                        var message = dto.Remarks; //处理理由
                        AbnormalLogActionEnum logActionEnum = AbnormalLogActionEnum.START;
                        taskStatus = (AbnormalTaskEnum)task.Status;
                        // 检查 status 是否是有效的枚举值
                        if (Enum.IsDefined(typeof(AbnormalTaskEnum), dto.Status.Value))
                        {
                            // 将 int 转换为枚举类型
                            dtoStatus = (AbnormalTaskEnum)dto.Status;
                        }
                        else
                            throw new AppException($"无效的状态值: {dto.Status}");
                        bool isOk = true;
                        //判断当前操作是否合法（基于上一级的状态）
                        switch (dtoStatus)
                        {
                            case AbnormalTaskEnum.TOCLAIM://待认领
                                break;
                            case AbnormalTaskEnum.DOING://处理中（待认领）
                                if ( taskStatus != AbnormalTaskEnum.TOCLAIM)
                                {
                                    isOk = false;
                                }
                                logActionEnum = AbnormalLogActionEnum.CLAIM;
                                break;
                            case AbnormalTaskEnum.TRANSFER://转派（处理中、退回）
                                if (taskStatus != AbnormalTaskEnum.DOING
                                    && taskStatus != AbnormalTaskEnum.RETURN)
                                {
                                    isOk = false;
                                }
                                logActionEnum = AbnormalLogActionEnum.TRANSFER;
                                break;
                            case AbnormalTaskEnum.RETURN://退回（转派、待确认）
                                if (taskStatus != AbnormalTaskEnum.TOCONFIRM 
                                    && taskStatus != AbnormalTaskEnum.TRANSFER)
                                {
                                    isOk = false;
                                }
                                if (string.IsNullOrWhiteSpace(message))
                                {
                                    throw new AppException($"【{dtoStatus.GetDescription()}】时需要备注");
                                }
                                logActionEnum = AbnormalLogActionEnum.RETURN;
                                break;
                            case AbnormalTaskEnum.TOCONFIRM://待确认（退回、处理中、转派）
                                if (taskStatus != AbnormalTaskEnum.RETURN
                                    && taskStatus != AbnormalTaskEnum.DOING
                                    && taskStatus != AbnormalTaskEnum.TRANSFER)
                                {
                                    isOk = false;
                                }
                                logActionEnum = AbnormalLogActionEnum.DOING;
                                break;
                            case AbnormalTaskEnum.DONE://确认（待确认）
                                if (taskStatus != AbnormalTaskEnum.TOCONFIRM)
                                {
                                    isOk = false;
                                }
                                if (string.IsNullOrWhiteSpace(message))
                                {
                                    throw new AppException($"【{dtoStatus.GetDescription()}】时需要备注");
                                }
                                logActionEnum = AbnormalLogActionEnum.CONFIRM;
                                break;
                            // 其他枚举值的处理
                            default:
                                throw new AppException($"未知的状态值: {taskStatus}");
                        }
                        if (!isOk)
                        {
                            throw new AppException($"该任务为【{taskStatus.GetDescription()}】状态" +
                                        $"，无法处理【{dtoStatus.GetDescription()}】业务！");
                        }
                        //判断当前处理人是否更变
                        var currentUser = UserContext.Current.UserName;
                        var LastProcessor = task.LastProcessor;//上一处理人
                        
                        if (dtoStatus == AbnormalTaskEnum.TRANSFER || dtoStatus == AbnormalTaskEnum.RETURN)
                        {
                            if (dtoStatus == AbnormalTaskEnum.TRANSFER)
                            {
                                if(dto.CurrentProcessor == task.CurrentProcessor 
                                    || dto.CurrentProcessor== dto.Initiator)
                                    throw new AppException($"无法转派给本人或者创建者！");
                            }
                            if (dtoStatus == AbnormalTaskEnum.TRANSFER)
                            {
                                currentUser = dto.CurrentProcessor;//转派的话使用前端传来的人
                                LastProcessor = UserContext.Current.UserName;
                            }
                            else
                            {
                                currentUser = task.LastProcessor;//退回的话就返回上一处理人
                                LastProcessor = task.CurrentProcessor;//退回的话就需要切换回上一处理人
                            }
                        }
                        //待确认时返回到创建人手上
                        if(dtoStatus == AbnormalTaskEnum.TOCONFIRM)
                        {
                            currentUser = task.Initiator;
                            LastProcessor = task.CurrentProcessor;//退回的话就需要切换回上一处理人
                        }
                        await _repository.DbContext.Updateable<Ads_Task>()
                            .SetColumns(a => a.Status == dto.Status)
                            .SetColumns(a => a.LastProcessor == LastProcessor)//上一处理人
                            .SetColumns(a => a.CurrentProcessor == currentUser)//下一处理人
                            .SetColumns(a => a.TreatmentMethod == dto.TreatmentMethod)
                            .SetColumns(a => a.TreatmentResult == dto.TreatmentResult)
                            .SetColumns(a => a.TreatmentAttachments == dto.TreatmentAttachments)
                            .SetColumns(a => a.ModifyTime == DateTime.Now)
                            .Where(a => a.TaskId == dto.TaskId)
                            .ExecuteCommandAsync();
                        //添加任务日志
                        await _taskLog.InsertLog(id, logActionEnum, message);
                    }
                    #endregion
                }
                if (!inTrans) await _repository.SqlSugarClient.Ado.CommitTranAsync();
                return id;
            }
            catch (Exception e)
            {
                if (!inTrans) _repository.SqlSugarClient.Ado.RollbackTran();
                throw new AppException("保存失败！详情：" + e.Message);
            }
        }

        /// <summary>
        /// 获取异常任务分页数据
        /// </summary>
        /// <param name="pageIn"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<AbnormalTaskPageOutDto> GetPage(AbnormalTaskPageInDto pageIn)
        {
            pageIn ??= new AbnormalTaskPageInDto();
            AbnormalTaskPageOutDto result = new AbnormalTaskPageOutDto();
            List<AbnormalTaskDto> taskDtos = new List<AbnormalTaskDto>();
            string currentUser = UserContext.Current.UserName;

            if (pageIn.DataType==1)
            {
                var query = _repository.DbContext.Queryable<Ads_Task>()
                .Where(t => t.IsValid == 1)
                .WhereIF(pageIn.status.HasValue, t => t.Status == pageIn.status)
                .WhereIF(pageIn.priority.HasValue, t => t.Priority == pageIn.priority)
                .WhereIF(!string.IsNullOrWhiteSpace(pageIn.abnormalTaskCode), t => t.TaskCode.Contains(pageIn.abnormalTaskCode))
                .WhereIF(pageIn.abnormalTypeId > 0, t => t.AbnormalTypeId == pageIn.abnormalTypeId)
                .Where(t => t.Initiator == currentUser)
                .OrderByDescending(t => t.CreateTime);
                result.total = await query.CountAsync();
                var tasks = await query.Skip((pageIn.limit - 1) * pageIn.rows)
                .Take(pageIn.rows).ToListAsync();

                //根据不同人查询不同数据
                foreach (var task in tasks)
                {
                    AbnormalTaskDto taskDto = _mapper.Map<AbnormalTaskDto>(task);
                    //创建者可见
                    if (taskDto.Initiator == UserContext.Current.UserName)
                    {
                        //状态为新增、待确认-可编辑
                        if ((AbnormalTaskEnum)task.Status == AbnormalTaskEnum.TOCLAIM
                            || (AbnormalTaskEnum)task.Status == AbnormalTaskEnum.TOCONFIRM)
                        {
                            taskDto.IsRead = false;
                        }
                        else
                        {
                            //其他状态-只读
                            taskDto.IsRead = true;
                        }

                        taskDtos.Add(taskDto);
                        continue;
                    }
                }
            }
            else if (pageIn.DataType == 2)
            {
                //查询所有经手的任务
                var taskIds = await _repository.DbContext.Queryable<Ads_TaskLog>()
                    .Where(t => t.Operator == currentUser)
                    .Select(t => t.TaskId)
                    .Distinct()
                    .ToListAsync();

                var query = _repository.DbContext.Queryable<Ads_Task>()
                    .Where(t => t.IsValid == 1)
                    .Where(t => taskIds.Contains(t.TaskId))
                    .WhereIF(pageIn.status.HasValue, t => t.Status == pageIn.status)
                    .WhereIF(pageIn.priority.HasValue, t => t.Priority == pageIn.priority)
                    .WhereIF(!string.IsNullOrWhiteSpace(pageIn.abnormalTaskCode), t => t.TaskCode.Contains(pageIn.abnormalTaskCode))
                    .WhereIF(pageIn.abnormalTypeId > 0, t => t.AbnormalTypeId == pageIn.abnormalTypeId)
                    .OrderByDescending(t => t.ModifyTime);
                result.total = await query.CountAsync();
                var tasks = await query.Skip((pageIn.limit - 1) * pageIn.rows)
                .Take(pageIn.rows).ToListAsync();
                taskDtos.AddRange(_mapper.Map<List<AbnormalTaskDto>>(tasks));

                //待处理者可见
                foreach (var taskDto in taskDtos)
                {
                    taskDto.IsRead = true;
                }
            }
            else if(pageIn.DataType == 3)
            {
                //查询所有待处理任务
                List<Ads_Task> temps = new List<Ads_Task>();

                var tasks = await Db.Queryable<Ads_Task>()
                    .Where(t => t.IsValid == 1)
                    .Where(t => t.Status != (int)AbnormalTaskEnum.DONE)
                    .WhereIF(pageIn.status.HasValue, t => t.Status == pageIn.status)
                    .WhereIF(pageIn.priority.HasValue, t => t.Priority == pageIn.priority)
                    .WhereIF(!string.IsNullOrWhiteSpace(pageIn.abnormalTaskCode), t => t.TaskCode.Contains(pageIn.abnormalTaskCode))
                    .WhereIF(pageIn.abnormalTypeId > 0, t => t.AbnormalTypeId == pageIn.abnormalTypeId)
                    .OrderByDescending(t=>t.Priority)
                    .ThenByDescending(t => t.ModifyTime)
                    .ToListAsync();

                //待认领的单独处理
                foreach (var item in tasks) {
                    //当前处理人是本人添加待处理
                    if (item.CurrentProcessor==currentUser)
                    {
                        temps.Add(_mapper.Map<Ads_Task>(item));
                        continue;
                    }

                    //待认领的任务需要判断是否属于当前用户
                    if (item.Status == (int)AbnormalTaskEnum.TOCLAIM)
                    {
                        //本人不参与待认领任务
                        if (item.Initiator==currentUser)
                        {
                            continue;
                        }
                        //获取当前异常类型的责任人或者责任部门
                        var abnormalType = await _repository.DbContext.Queryable<Ads_AbnormalType>()
                            .Where(t => t.AbnormalTypeId == item.AbnormalTypeId).FirstAsync();
                        if (abnormalType != null) {
                            //获取责任部门
                            var responsibleDept = JsonConvert.DeserializeObject<List<long>>(
                                abnormalType.ResponsibleDept==null?"[]": abnormalType.ResponsibleDept);
                            if (responsibleDept != null&& responsibleDept.Count()>0)
                            {
                                var userDept = UserContext.Current.DeptIds;
                                if (userDept.Intersect(responsibleDept).Any())
                                {
                                    //获取责任人
                                    var responsiblePersons = JsonConvert.DeserializeObject<List<string>>(
                                        abnormalType.ResponsiblePersons==null?"[]": abnormalType.ResponsiblePersons);
                                    if (responsiblePersons == null || !responsiblePersons.Any() || responsiblePersons.Contains(currentUser))
                                    {
                                        temps.Add(_mapper.Map<Ads_Task>(item));
                                    }
                                }
                            }
                            else
                            {
                                //获取责任人
                                var responsiblePersons = JsonConvert.DeserializeObject<List<string>>(
                                    abnormalType.ResponsiblePersons==null? "[]" : abnormalType.ResponsiblePersons);
                                if (responsiblePersons != null && responsiblePersons.Contains(currentUser))
                                {
                                    temps.Add(_mapper.Map<Ads_Task>(item));
                                    continue;
                                }
                            }
                        }
                    }
                }

                //分页处理
                result.total = temps.Count;
                temps = temps.Skip((pageIn.limit - 1) * pageIn.rows).Take(pageIn.rows).ToList();

                //待处理者可见
                taskDtos.AddRange(_mapper.Map<List<AbnormalTaskDto>>(temps));
                foreach (var taskDto in taskDtos)
                {
                    taskDto.IsRead = false;
                }
            }

            result.abnormalTasks = taskDtos;

            return result;
        }

        /// <summary>
        /// 获取任务日志
        /// </summary>
        /// <param name="taskId"></param>
        /// <returns></returns>
        public async Task<List<TaskLogDto>> GetTaskLog(long taskId)
        {
            List<TaskLogDto> datas = new List<TaskLogDto>();
            //获取日志记录
            var logs = await _repository.DbContext.Queryable<Ads_TaskLog>()
                .Where(t => t.TaskId == taskId)
                .OrderByDescending(t => t.CreateTime)
                .ToListAsync();
            
            foreach (var log in logs)
            {
                TaskLogDto taskLogDto = new TaskLogDto();
                var users = await SysDb.Queryable<Sys_User>().Where(x => x.IsValid == 1).Select(t => new keyValueDto
                {
                    key = t.UserName,
                    value = t.UserTrueName
                }).ToListAsync();
                taskLogDto.Operator = users.FirstOrDefault(x => x.key == log.Operator)?.value;
                var operation = (AbnormalLogActionEnum)log.Operation;
                taskLogDto.Operation = operation.GetDescription();
                var operationType = (AbnormalLogTypeEnum)log.OperationType;
                taskLogDto.OperationType = operationType.GetDescription();
                taskLogDto.Remarks = string.IsNullOrWhiteSpace(log.Remarks)?"": log.Remarks;
                taskLogDto.CreateTime = log.CreateTime;
                datas.Add(taskLogDto);
            }
            return datas;
        }

        /// <summary>
        /// 获取异常任务详情
        /// </summary>
        /// <param name="taskId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<AbnormalTaskDto> GetDetail(long taskId)
        {
            var data = await _repository.DbContext.Queryable<Ads_Task>()
                .Where(a => a.TaskId == taskId&&a.IsValid==1)
                .FirstAsync();
            return _mapper.Map<AbnormalTaskDto>(data);
        }

        #region 一般方法
        public string GenerateCode()
        {
            // 获取当天日期部分
            string today = DateTime.Now.ToString("yyyyMMdd");

            // 查询数据库中当天最大的code
            var maxCode = Db.Queryable<Ads_Task>()
                .Where(x => x.TaskCode.StartsWith(today))
                .Max(x => x.TaskCode);

            // 如果当天没有记录，则从001开始
            if (string.IsNullOrEmpty(maxCode))
            {
                return $"{today}001";
            }

            // 获取最大code的序列号部分
            string sequencePart = maxCode.Substring(8);
            int sequenceNumber = int.Parse(sequencePart);
            if (sequenceNumber == 999)
            {
                throw new Exception("当天的业务编号最大为999,无法再添加！");
            }
            // 生成新的序列号
            string newSequence = (sequenceNumber + 1).ToString("D3");

            // 返回新的code
            return $"{today}{newSequence}";
        }
        #endregion
    }
}
